package org.huwei.data.manager;

import java.util.List;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;

/**
 * 	数据源管理策略执行接口 
 * 	作用：
 * 		作为一个或多个数据源同一个方法调用时，该方法具体如何处理的一个回调接口，该接口将允许用户实现自定义处理流程；
 * 	使用：
 * 		实现该接口，并实现类加载到spring容器中即可；{@link DataSourceManagerFacotry}使用了依赖注入，当存在该接口的实现类时，将自动注入，并使用注入的对象；
 * 	约定：
 * 	1，以org.springframework.core.annotation.Order注解给定数字作为优先级排序，数字越小则表示优先执行；	
 * 
 * 	《data数据源默认处理策略》
 * 	默认规则：
 * 	1，默认从优先级高数据源开始执行，如果找到需要的结果，则直接返回，不再执行后续数据源；反之，则依次执行所有数据源；
 * 	建议：
 * 	数据源的优先级排序，最好使用的查询顺序为：内存 -> 本地缓存（一级缓存，如：ehcache） -> 服务器缓存（二级缓存，如：redis）-> rpc -> db 
 * @author huwei
 * @date 2019-4-4
 */
public interface DataSourceManagementStrategy {
	
	final Logger log = LoggerFactory.getLogger(DataSourceManagementStrategy.class);

	/**
	 * 	默认的数据源的执行策略，默认以用户所定义的数据源的执行优先级先后执行，而如果优先级高的数据源对象调用其方法得到了返回值，则后续数据源将不再得到执行；
	 * 	解释：
	 * 	数据源优先级使用{@link Order} 注解定义；
	 * @param dataSourceOperationList 数据源操作对象的队列，该队列以优先级高低排序；
	 * @return 数据源当前方法的执行返回值；
	 */
	default Object handle(List<DataSourceOperation> dataSourceOperationList) {
		Object result = null;
		for(int i = 0 ,len = dataSourceOperationList.size() ;i < len ;++i) {
			DataSourceOperation opera = dataSourceOperationList.get(i);
			if(!opera.isInvoke()) {
				try {
					result = opera.invokeCurrentMethod();
				} catch (Throwable e) {
					log.error(e.getMessage(), e);
					throw new RuntimeException(e);
				}
			}
			if(Objects.nonNull(result)) {
				break;
			}
		}
		clearInvokeMarked(dataSourceOperationList);
		return result;
	}
	
	/**
	 * 	清除给定数据源操作对象的方法调用记录
	 * @param dataSourceOperationList
	 */
	default void clearInvokeMarked(List<DataSourceOperation> dataSourceOperationList) {
		for(int i = 0 ,len = dataSourceOperationList.size() ;i < len ;++i) {
			dataSourceOperationList.get(i).clearInvoke();
		}
	}
}
